#ifndef __BASE__H__
#define __BASE__H__

#include <vector>
#include <map>
#include <list>
#include <set>
#include <stdio.h>  // for sprintf
#include <string.h> // for memset
#include <iostream> // for cout
#include <string>
#include <algorithm> // for for_each
#include <exception>

#ifndef _WIN32
//#pragma message("Linux!!!")
//compile @ linux
#define stricmp strcasecmp

#else

//#pragma message("Windows!!!")
//compile @ windows

#endif

using namespace std;


//边界限制，默认的标准数独边界为1－9
enum enumBound {LOWER_BOUNDER=1,UPPER_BOUNDER=9,INVALID_BOUNDER=UPPER_BOUNDER+1};
//支持的导出格式（也可导入）
enum enumFormat {
    FormatNumber81      //81数格式
    ,FormatMultiLine    //81数，9x9矩阵
    ,FormatSimpleTable  //简单的Ascii Table格式 （以上几种格式可导入）

    ,FormatFullTable    //完整的候选数表格格式（候选数紧凑不固定位置）
    ,FormatFullTableStable //完整的候选数表格格式（候选数固定位置，不紧凑）
    //是否增加带行列的格式？
};
//标志题局的状态
enum enumPuzzleStatus { PuzzleIsOver,PuzzleHasError,PuzzleIsPlaying};
//标志候选数的状态：无，正常，标记删除
enum TAG_ENUM{STA_NONE,STA_NORMAL,STA_TAG};
//数格集合的类型码，X列，Y行，Z宫，XX是为X SUDOKU准备，ZA是为锯齿SUDOKU准备
enum CellSet_TYPE{CellSet_X,CellSet_Y,CellSet_Z,CellSet_XX,CellSet_ZA}; //XX for XSudoku....
//准备支持的数独类型码，缺省就是标准数独
enum SUDOKU_TYPE{DEFAULT_SUDOKU=0,STANDARD_SUDOKU=0,X_SUDOKU,HACKLE_SUDOKU};
//支持的操作类别
enum OpType{
     OperationSetNumber			//做填数操作
    ,OperationUnsetNumber		//做取消填数的操作（非自动解题操作）
    ,OperationTagCandidateDelete	//做候选数标记删除操作
    ,OperationTagCandidateNormal	//做候选数正常操作（非自动解题操作）
    ,OperationTagCandidateNone	//做候选数排除操作（非用户操作）
};


//字符串异常类，用来抛出一些异常的文字信息
class StringException:public exception
{
public:
    StringException(const char *str)
    {
        strbuf=str;
    }
    StringException(const string &str)
    {
        strbuf=str;
    }
    ~StringException() throw()
    {

    }

    virtual const char* what() const throw()
    {
        return strbuf.c_str();
    }

private:
    string strbuf;
};

//IObject：大部分类都实现此接口，以便在日志或者描述信息里使用toString来获取名称信息
class IObject //提供一些公共的基础的接口，比如toString
{
public:
	virtual const char* toString() {return "";};
	virtual ~IObject(){};
};

//坐标类，坐标范围受enumBound限制
class Point
{
private:
	char pszName[5];
	int x;
	int y;
public:
	//默认构造函数，构造的坐标是非法的0,0（是否不应该有这个呢？）
	Point() throw()
	{
		x=0;
		y=0;
		memset(pszName,0,sizeof(pszName));
	}

	//初始化坐标的构造函数（附带边界检查）
	Point(int vx,int vy) throw()
	{
		x=0;
		y=0;
		memset(pszName,0,sizeof(pszName));
		try{
			setX(vx);
			setY(vy);
		}
		catch   (const   exception   &e)  
		{  
			cout   <<   e.what()   <<   endl;  
		}
		catch(...)
		{
			cerr<<"Exception on ctor() on " << __FILE__ << " Line:" <<__LINE__<<endl;
		}
	}

	virtual int getX() const 
	{
		return this->x;
	}
	virtual int getY() const 
	{
		return this->y;
	}
	virtual int setX(int v)
	{
		if(v<LOWER_BOUNDER || v>UPPER_BOUNDER)
		{
			char psztmp[200];
			sprintf(psztmp,"Point X[%d] out of bounder[%d - %d]!",v,LOWER_BOUNDER,UPPER_BOUNDER);
                        throw StringException(psztmp);
		}
		x=v;
		updateString();
		return x;
	}
	virtual int setY(int v)
	{
		if(v<LOWER_BOUNDER || v>UPPER_BOUNDER)
		{
			char psztmp[200];
			sprintf(psztmp,"Point Y[%d] out of bounder[%d - %d]!",v,LOWER_BOUNDER,UPPER_BOUNDER);
                        throw StringException(psztmp);
		}
		y=v;
		updateString();
		return y;
	}

	virtual int setXY(int vx,int vy)
	{
		setX(vx);
		setY(vy);
		return 0;
	}

	//判断两个坐标是否一致相等
	virtual bool isEqual(const Point &p) const 
	{
		return p.getX()==x && p.getY()==y;
	}

	virtual const char * toString()
	{
		return pszName;
	}
protected:
	//生成数独里惯用的坐标表示方法，A－I行，1－9列，表示为先行后列的两个字符
	virtual void updateString()
	{
		pszName[0]='A'-1+y;
		pszName[1]='0'+x;
	}
};


//定义类型Number表示操作数字，以示区别
typedef unsigned int Number;
typedef vector<Number> Numbers;
typedef vector<Point> Points;
#define NumberIsEmpty(n) ( n==0 )
#define NumberIsValid(n) ( LOWER_BOUNDER<=n && n<=UPPER_BOUNDER )
#define NumberToChar(n) ( NumberIsValid ( n ) ? ( '0'+n ):'0')

template <typename T>
string implode(const char *delimiter,T array)
{
    string str="";
    typename T::iterator itor=array.begin();
    if(itor!=array.end())
    {
        str=*array.begin();
        ++itor;
    }
    for(;itor!=array.end();++itor)
    {
        str += delimiter;
        str += *itor;
    }
    return str;
}

template <typename T>
vector<string> getStrings(T objs)
{
    vector<string> strs;
    typename T::iterator itor=objs.begin();
    for(;itor!=objs.end();++itor)
    {
        strs.push_back((*itor)->toString());
    }
    return strs;
}


#endif //__BASE__H__
